//
//  XLGendQueueManager.m
//  Etion
//
//  Created by  user on 11-4-19.
//  Copyright 2011 GuangZhouXuanWu. All rights reserved.
//

#import "XLGSendQueueManager.h"
#import "XLGSendQueueManagerInternal.h"
#import "OperationQueueShell.h"
#import "XLGSendItem+SendItemHelper.h"
#import "XLGManagerService.h"

NSString *const XLGSendQueueManagerBackgroundMaintainKey = @"XLGSendQueueManagerBackgroundMaintainKey";

NSString *const XLGSendQueueDefaultDBFile = @"SendQueue.db";

NSString *const XLGSendQueueDataFolder = @"SendQueueData";

NSString *const XLGSendQueueManagerDefaultKey = @"XLGSendQueueManagerDefaultKey";

@interface XLGSendQueueManager ()<CBackgroundMaintainDelegate>

@end

@implementation XLGAddSendItem

- (id)initWhthSendQueueManager:(XLGSendQueueManager *)sendQueueManager messageinstance:(XLGSendQueueIndex *)mi UITarget:(id)target
{
    self = [super init];
    _sendQueueManager = [sendQueueManager retain_mm];
    _mi = [mi retain_mm];
    _uitarget = [target retain_mm];
    return self;
}

- (void)dealloc
{
    [_sendQueueManager release_mm];
    [_mi release_mm];
    [_uitarget release_mm];
    superdealloc_mm;
}

- (void)addSendItem
{
    [_sendQueueManager->_arraylockqueue dispatchThreadSync:^
    {
        _mi.serialNo = 9999;
        [_sendQueueManager->_commonindex addSendQueueIndex:_mi];
        
        NSMutableArray *arQueue = _sendQueueManager->_arQueue;
        
        __block NSInteger i = 0;
        
        if([XLGContext context].m_bIsoffline == NO)
        {
            _mi.sendStatus = XLGSendItemStatusTypeWaiting;
        for (i = arQueue.count - 1; i >= 0; i--)
        {
            XLGSendQueueIndex *mi = ((XLGSendItem *) [arQueue objectAtIndex:i]).mi;
            XLGSendItemStatusType sendStatus = mi.sendStatus;
            if (XLGSendItemStatusTypeStop != sendStatus &&
                XLGSendItemStatusTypeFailed != sendStatus &&
                XLGSendItemStatusTypeRejest != sendStatus)
            {
                i++;
                break;
            }
        }
        }
        else
        {
            _mi.sendStatus = XLGSendItemStatusTypeFailed;
            
            for (i = arQueue.count - 1; i >= 1; i--)
            {
                XLGSendQueueIndex *mi = ((XLGSendItem *) [arQueue objectAtIndex:i]).mi;
                if (XLGSendItemStatusTypeSending == mi.sendStatus || XLGSendItemStatusTypeUpprioritySend == mi.sendStatus || XLGSendItemStatusTypeWaiting == mi.sendStatus || XLGSendItemStatusTypeStop == mi.sendStatus || XLGSendItemStatusTypeFailed == mi.sendStatus)
                    break;
            }
            i++;
        }
        
        i = MAX(0, i);
        
        XLGSendItem *si = [[XLGSendItem alloc] initWhthSendQueueManager:_sendQueueManager messageinstance:_mi];
        if (_uitarget != nil&& [_uitarget nextResponder] != nil)
        {
            [si addSendItemDelegate:_uitarget];
        }
        [arQueue insertObject:si atIndex:i];
        [si release_mm];
        
        [_sendQueueManager->_commonindex modifySendIndexSerialNo:^NSInteger(NSInteger(^modify)(NSUInteger index,NSString *extendID))
        {
            NSInteger nResult = FALSE;
            for (; i < arQueue.count; i++)
            {
                XLGSendQueueIndex *mi = ((XLGSendItem *) [arQueue objectAtIndex:i]).mi;
                mi.serialNo = i;
                nResult =  modify(i,mi.extendID);
                if(nResult != YES)
                    break;
            }
            return nResult;
        }];
        
        
        [_sendQueueManager exchangeSendItemStatus:si];
        
#ifdef DEBUG
        //	for(XLGSendItem* si in arQueue)
        //	{
        //		CMessageInstanceObj* mi=si.mi;
        //		NSLog(@"addsenditem--id:%@,num:%i,type:%i,title%@",mi.m_szExtendid,mi.m_nStatus,mi.m_nMessagetype,mi.m_szTitle);
        //	}
#endif
        
    }];

    if ([XLGContext context].m_bIsoffline == YES)
        return;

    [_sendQueueManager openScanThread];
}

@end

@implementation XLGSendItem

@synthesize mi = _mi;
@synthesize currentSendingFile = _currentsendingfile;
@synthesize nHadsendedbytes = _nHadsendedbytes;
@synthesize nTotalwillsendbytes = _nTotalwillsendbytes;


- (id)initWhthSendQueueManager:(XLGSendQueueManager *)sendQueueManager messageinstance:(XLGSendQueueIndex *)mi
{
    self = [super init];
    _sendQueueManager = [sendQueueManager retain_mm];
    _mi = [mi retain_mm];

    _arSendItemDelegate = [NSMutableArray new];
    
    _managerService = [XLGManagerService new];

    return self;
}

- (void)dealloc
{
    [_managerService release_mm];
    [_sendQueueManager release_mm];
    [_mi release_mm];
    [_currentsendingfile release_mm];
    [_arSendItemDelegate release_mm];
    superdealloc_mm;
}

- (void)addSendItemDelegate:(id<XLGSendItemDelegate>)obj
{
    [_sendQueueManager->_uilockqueue dispatchThreadSync:^
    {
        if (NO == [_arSendItemDelegate containsObject:obj])
            [_arSendItemDelegate addObject:obj];
    }];
}

- (void)removeSendItemDelegate:(id<XLGSendItemDelegate>)obj
{
    [_sendQueueManager->_uilockqueue dispatchThreadSync:^
    {
        if (YES == [_arSendItemDelegate containsObject:obj])
            [_arSendItemDelegate removeObject:obj];
    }];
}

- (void)removeAllSendItemDelegate
{
    [_sendQueueManager->_uilockqueue dispatchThreadSync:^
    {
        [_arSendItemDelegate removeAllObjects];
    }];
}

- (void)setUIOperationDelegateFromArray:(NSArray *)delegate
{
    [_sendQueueManager->_uilockqueue dispatchThreadSync:^
    {
        [_arSendItemDelegate removeAllObjects];
        
        if (delegate.count > 0)
            [_arSendItemDelegate addObjectsFromArray:delegate];
    }];
}

- (void)setForceTerminal:(BOOL)forceTerminal
{
    _forceTerminal = forceTerminal;
    [_managerService terminateRequest];
}

- (void)suspendSendItem:(BOOL)enterForceground
{
    _bWillenterforceground = enterForceground;
    [_managerService terminateRequest];
}

- (XLGResult*)sendItemDataFormatCategoryOpeateion:(NSString *)extendID sendType:(NSUInteger)sendType textCache:(NSString *)textCacheFilePath multiMediaCache:(NSString *)mediaCacheFilePath messageManagerAttach:(XMSDataOperationManager *)attach
{
    return [XLGResult result];
}

- (void)sendItemSuccessCategoryOpeateion:(NSString *)szExtendid
{
}

-(BOOL)startItem
{
    [super startItem];
    
    DispatchGlobalThreadAsync(^
    {
        [self main];
        
        [self stopItem];
    });
    return YES;
}

- (void)main
{
    _mi.sendStatus = XLGSendItemStatusTypeSending;

    ReleaseObj(_currentsendingfile);
    _currentsendingfile = [@"准备发送" retain_mm];
    [_sendQueueManager exchangeSendItemStatus:self];
    ReleaseObj(_currentsendingfile);

    NSMutableArray *arQueue = [[_sendQueueManager->_arQueue retain_mm]autorelease_mm];
    
    XLGResult *result = [self sendItemProc];
    
    [_sendQueueManager->_arraylockqueue dispatchThreadSync:^
    {
        switch (result.outResult)
        {
            case TRUE:
            {
                [_sendQueueManager->_commonindex modifySendedSendIndex:_mi.extendID];
                
                _mi.sendStatus = XLGSendItemStatusTypeSended;
#ifdef DEBUG
                //			NSLog(@"senditemremoveatindex--id:%@,num:%i",mi.m_szExtendid,mi.m_nStatus);
#endif
                [arQueue removeObjectAtIndex:_mi.serialNo];
                
                NSUInteger nLen = arQueue.count;
                
                [_sendQueueManager->_commonindex modifySendIndexSerialNo:^NSInteger(NSInteger(^modify)(NSUInteger index,NSString *extendID))
                {
                    NSInteger nResult = FALSE;
                    for (NSUInteger i = _mi.serialNo; i < nLen; i++)
                    {
                        XLGSendQueueIndex *mi = ((XLGSendItem *) [arQueue objectAtIndex:i]).mi;
                        mi.serialNo -= 1;
                        nResult = modify(mi.serialNo,mi.extendID);
                        if(nResult != YES)
                            break;
                    }
                    return nResult;
                }];
                
                
                [self sendItemSuccessCategoryOpeateion:_mi.extendID];
                
#ifdef DEBUG
                //			NSLog(@"senditem--id:%@,%@发送成功",mi.m_szExtendid,mi.m_szTitle);
                //			for(XLGSendItem* si in arQueue)
                //			{
                //				CMessageInstanceObj* mi=si.mi;
                //				NSLog(@"senditem--id:%@,num:%i,sendtype:%i,type:%i,title:%@",mi.m_szExtendid,mi.m_nStatus,mi.m_nReadstatus,mi.m_nMessagetype,mi.m_szTitle);
                //			}
#endif
                [_sendQueueManager exchangeSendItemStatus:self];
                
                [self removeAllSendItemDelegate];
                
                break;
            }
            case FALSE:
            default:
            {
                if (YES == _bWillenterforceground)
                {
                    _mi.sendStatus = XLGSendItemStatusTypeNextTimeContinue;
                    XLGSendItem *si = [[XLGSendItem alloc] initWhthSendQueueManager:_sendQueueManager messageinstance:_mi];
                    [si setUIOperationDelegateFromArray:_arSendItemDelegate];
                    si->_currentsendingfile = [_currentsendingfile retain_mm];
                    si->_nHadsendedbytes = _nHadsendedbytes;
                    si->_nTotalwillsendbytes = _nTotalwillsendbytes;
                    [arQueue insertObject:si atIndex:_mi.serialNo];
                    [si release_mm];
                    [arQueue removeObjectAtIndex:_mi.serialNo + 1];
                    _bWillenterforceground = NO;
                    
                }else if(YES == _forceTerminal)
                {
                    _mi.sendStatus = XLGSendItemStatusTypeForceTerminal;
                    
                    [_sendQueueManager->_commonindex deleteSendIndexWithExtendID:@[_mi.extendID]];
                    
                    [XMSFileHelper deleteFileDir:[NSString stringWithFormat:@"%@/%@/%@", [XLGContext context].m_szUserdefaulteppath, XLGSendQueueDataFolder, _mi.extendID]];
                    
                    [arQueue removeObjectAtIndex:_mi.serialNo];
                    
                    NSUInteger nLen = arQueue.count;
                    
                    [_sendQueueManager->_commonindex modifySendIndexSerialNo:^NSInteger(NSInteger(^modify)(NSUInteger index,NSString *extendID))
                    {
                        NSInteger nResult = FALSE;
                        for (NSUInteger i = _mi.serialNo; i < nLen; i++)
                        {
                            XLGSendQueueIndex *mi = ((XLGSendItem *) [arQueue objectAtIndex:i]).mi;
                            mi.serialNo -= 1;
                            nResult = modify(mi.serialNo,mi.extendID);
                        }
                        return nResult;
                    }];
                    
                    [_sendQueueManager exchangeSendItemStatus:self];
                    
                    [self removeAllSendItemDelegate];
                }
                else
                {
                    _mi.sendStatus = XLGSendItemStatusTypeFailed;
                    
                    if (arQueue.count > 0)
                    {
                        NSUInteger i = 0;
                        for (i = arQueue.count - 1; i >= 1; i--)
                        {
                            XLGSendItem *si = [arQueue objectAtIndex:i];
                            XLGSendQueueIndex *mi = si.mi;
                            if (XLGSendItemStatusTypeSending == mi.sendStatus || XLGSendItemStatusTypeUpprioritySend == mi.sendStatus || XLGSendItemStatusTypeWaiting == mi.sendStatus ||
                                XLGSendItemStatusTypeStop == mi.sendStatus || XLGSendItemStatusTypeFailed == mi.sendStatus)
                                break;
                        }
                        i++;
                        
                        XLGSendItem *si = [[XLGSendItem alloc] initWhthSendQueueManager:_sendQueueManager messageinstance:_mi];
                        //	si.m_currentsendingfile=self.m_currentsendingfile;
                        [arQueue insertObject:si atIndex:i];
                        [si release_mm];
                        [arQueue removeObjectAtIndex:_mi.serialNo];
                        
                        [_sendQueueManager->_commonindex modifySendIndexSerialNo:^NSInteger(NSInteger(^modify)(NSUInteger index,NSString *extendID))
                        {
                            NSInteger nResult = FALSE;
                            for (NSUInteger j = 0; j < i; j++)
                            {
                                XLGSendQueueIndex *mi = ((XLGSendItem *) [arQueue objectAtIndex:j]).mi;
                                mi.serialNo = j;
                                nResult = modify(mi.serialNo,mi.extendID);
                                if(nResult != YES)
                                    break;
                            }
                            return nResult;
                        }];
                    }
                }
                
                [_sendQueueManager->_commonindex modifySendIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger index,NSString *extendID,NSUInteger sendStatus))
                {
                    return modify(_mi.serialNo,_mi.extendID,_mi.sendStatus);
                }];
                
                
#ifdef DEBUG
                //			NSLog(@"senditem--id:%@,%@发送失败",mi.m_szExtendid,mi.m_szTitle);
                //			for(XLGSendItem* si in arQueue)
                //			{
                //				CMessageInstanceObj* mi=si.mi;
                //				NSLog(@"senditem--id:%@,num:%i,sendtype:%i,type:%i,title:%@",mi.m_szExtendid,mi.m_nStatus,mi.m_nReadstatus,mi.m_nMessagetype,mi.m_szTitle);
                //			}
#endif
                [_sendQueueManager exchangeSendItemStatus:self];
                
                [self removeAllSendItemDelegate];
                
                break;
            }
            case PROTOCOLRETOBJNIL:
            {
                _mi.sendStatus = XLGSendItemStatusTypeRejest;

                if (arQueue.count > 0)
                {
                    XLGSendItem *si = [[XLGSendItem alloc] initWhthSendQueueManager:_sendQueueManager messageinstance:_mi];
                    //	si.m_currentsendingfile=self.m_currentsendingfile;
                    [arQueue insertObject:si atIndex:arQueue.count];
                    [si release_mm];
                    [arQueue removeObjectAtIndex:_mi.serialNo];
                    [_sendQueueManager->_commonindex modifySendIndexSerialNo:^NSInteger(NSInteger(^modify)(NSUInteger index,NSString *extendID))
                    {
                        NSInteger nResult = FALSE;
                        for (NSUInteger j = 0; j < arQueue.count; j++)
                        {
                            XLGSendQueueIndex *mi = ((XLGSendItem *) [arQueue objectAtIndex:j]).mi;
                            mi.serialNo = j;
                            nResult = modify(mi.serialNo,mi.extendID);
                            if(nResult != YES)
                                break;
                        }
                        return nResult;
                    }];
                    
                    [_sendQueueManager->_commonindex modifySendIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger index,NSString *extendID,NSUInteger sendStatus))
                     {
                         return modify(_mi.serialNo,_mi.extendID,_mi.sendStatus);
                     }];
                    
#ifdef DEBUG
                    //				NSLog(@"senditem--id:%@,%@服务器拒绝接收",mi.m_szExtendid,mi.m_szTitle);
                    //				for(XLGSendItem* si in arQueue)
                    //				{
                    //					CMessageInstanceObj* mi=si.mi;
                    //					NSLog(@"senditem--id:%@,num:%i,sendtype:%i,type:%i,title:%@",mi.m_szExtendid,mi.m_nStatus,mi.m_nReadstatus,mi.m_nMessagetype,mi.m_szTitle);
                    //				}
#endif
                }
                
                [_sendQueueManager exchangeSendItemStatus:self];
                
                [self removeAllSendItemDelegate];
                
                break;
            }
        }
    }];
    
    if(_bWillenterforceground != YES && [UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
    {
        if([XMSBackgroundMaintain isBackgrounsService:XLGSendQueueManagerBackgroundMaintainKey] && [_sendQueueManager isNeedBackgroundMaintain] == NO)
            [XMSBackgroundMaintain backgroundTaskIsFinished:XLGSendQueueManagerBackgroundMaintainKey];
    }
}

@end

@implementation XLGSendQueueManager

@synthesize resendIntervalTime = _resendIntervalTime;

- (id)initWithSendQueueDBFile:(NSString*)dbFile
{
    self = [super init];
    
    _resendIntervalTime = 300;
    
    _pool = [XLGSendQueuePool new];
    _pool.maxCount = 1;
    
    _arraylockqueue = [[XMSDispatchQueueWrapper alloc]initWithName:"arraylockqueue"];
    _uilockqueue = [[XMSDispatchQueueWrapper alloc]initWithName:"uilockqueue"];
    
    _arSenditemanager = [NSMutableArray new];
    
    _commonindex = [[XLGSendQueueDBOperation alloc]initWithTablePath:[[XLGContext context].m_szUserdefaulteppath stringByAppendingPathComponent:dbFile]];
    
    return self;
}

- (id)init
{
    return [self initWithSendQueueDBFile:XLGSendQueueDefaultDBFile];
}

- (void)dealloc
{
    _bRunloop = NO;
    [_scanThread release_mm];
    _scanThread = nil;
    [_arSenditemanager release_mm];
    [_commonindex release_mm];
    [_arraylockqueue release_mm];
    [_uilockqueue release_mm];
    [_pool release_mm];
    superdealloc_mm;
}

-(void)setMaxSendingCount:(NSUInteger)maxSendingCount
{
    _pool.maxCount = maxSendingCount;
}

-(NSUInteger)maxSendingCount
{
    return _pool.maxCount;
}

- (void)addSendQueueManagerDelegate:(id<XLGSendQueueManagerDelegate>)obj
{
    [_uilockqueue dispatchThreadSync:^
    {
        if (NO == [_arSenditemanager containsObject:obj])
            [_arSenditemanager addObject:obj];
    }];
}

- (void)removeSendQueueManagerDelegate:(id<XLGSendQueueManagerDelegate>)obj
{
    [_uilockqueue dispatchThreadSync:^
    {
        if (YES == [_arSenditemanager containsObject:obj])
            [_arSenditemanager removeObject:obj];
    }];
}

- (void)addSendItem:(XLGSendQueueIndex *)mi uiTarget:(id)target
{
    mi.sendStatus = XLGSendItemStatusTypeWaiting;
    DispatchThread(^
    {
        XLGAddSendItem *item = [[[XLGAddSendItem alloc] initWhthSendQueueManager:self messageinstance:mi UITarget:target] autorelease_mm];
        [item addSendItem];
    });
}

- (void)addSendItem:(XLGSendQueueIndex *)mi
{
    [self addSendItem:mi uiTarget:nil];
}

- (void)initSendQueueManager
{
    _arQueue = [NSMutableArray new];

    [_commonindex getSendQueueIndexCompletion:^(NSInteger nResult, NSArray *items)
    {
        for (XLGSendQueueIndex *mi in items)
        {
            XLGSendItem *item = [[XLGSendItem alloc] initWhthSendQueueManager:self messageinstance:mi];
            [_arQueue addObject:item];
            [item release_mm];
        }
    }];

    if([XLGContext context].m_bIsoffline == YES || [XLGContext context].m_bIsofflinelogin == YES)
        _bSuspending = YES;
    
    if (_arQueue.count > 0)
    {
        [self resendAllFailedSendItem];

        [self openScanThread];
    }
}

- (NSUInteger)sendQueueCount
{
    __block NSInteger count = 0;
    [_arraylockqueue dispatchThreadSync:^
    {
        count = _arQueue.count;
    }];
    return count;
}

- (void)getFinishSendItemsAsyncCompletion:(void (^)(NSArray *finishedItems))completion
{
    DispatchThread(^
    {
        [_commonindex getFinishSendIndexCompletion:^(NSInteger nResult, NSArray *items)
        {
            completion(items);
        }];
    });
}

- (void)getFinishSendIndex:(NSString*(^)(NSString *condition))condition asynCompletion:(void(^)(NSArray *finishedItems))completion
{
    DispatchThread(^
    {
        [_commonindex getFinishSendIndex:condition completion:^(NSInteger nResult, NSArray *items)
        {
             completion(items);
        }];
    });
}

- (void)deleteFinishSendItems:(NSArray *)arGuid
{
    [_commonindex deleteSendIndexWithExtendID:arGuid];
}

- (void)deleteFinishSendItems:(NSArray *)arGuid asyncCompletion:(void (^)())completion
{
    DispatchThread(^
    {
        [self deleteFinishSendItems:arGuid];
        completion();
    });
}

-(void)deleteAllFinishSendItemsAsyncCompletion:(void (^)())completion
{
    DispatchThread(^
    {
        [_commonindex deleteFinishSendIndex];
    });
}

- (void)deleteSendIndex:(NSString *(^)(NSString *))condition asyncCompletion:(void (^)())completion
{
    DispatchThread(^
    {
        [_commonindex deleteFinishSendIndex:condition];
    });
}

- (NSInteger)sendAllFaildItem
{
    if (YES == [XLGContext context].m_bIsoffline)
        return NETWORKOFFLINE;
    
    [_arraylockqueue dispatchThreadSync:^
    {
        if (YES == [self resendAllFailedSendItem])
        {
            [self exchangeAllSendItemStatus:XLGSendItemStatusTypeFailed toNewType:XLGSendItemStatusTypeWaiting];
        }
        
        [self openScanThread];
    }];
    
    return 1;
}

- (NSInteger)resumeSendQueueManager
{
    if (YES == [XLGContext context].m_bIsoffline)
        return NETWORKOFFLINE;

    if (YES == [XLGContext context].m_bIsofflinelogin)
        return NETWORKOFFLINE;

    if (_bSuspending != YES)
        return NO;

    _bSuspending = NO;
    
    [_arraylockqueue dispatchThreadSync:^
    {
        if (_arQueue.count > 0)
        {
            if (YES == [self resendAllFailedSendItem])
            {
                [_uilockqueue dispatchThreadAsync:^
                {
                     for (NSUInteger i = 0; i < _arSenditemanager.count; i++)
                     {
                         id<XLGSendQueueManagerDelegate> obj = [_arSenditemanager objectAtIndex:i];
                         if([obj respondsToSelector:@selector(exchangeManager:allSendItemStatus:toNewType:)])
                             [obj exchangeManager:self allSendItemStatus:XLGSendItemStatusTypeFailed toNewType:XLGSendItemStatusTypeWaiting];
                     }
                }];
            }
            
            [self openScanThread];
        }
    }];

    return YES;
}

- (void)suspendSendQueueManager
{
    _bSuspending = YES;
    _bRunloop = NO;
    [_scanCondition signal];
    [_scanThread release_mm];
    _scanThread = nil;
    BOOL enterForceground = [UIApplication sharedApplication].applicationState == UIApplicationStateBackground ? YES : NO;
    [_arraylockqueue dispatchThreadSync:^
    {
        for (XLGSendItem *i in _pool.items)
            [i suspendSendItem:enterForceground];
    }];
}

- (void)releaseSendQueueManager
{
    _bSuspending = YES;
    _bRunloop = NO;
    [_scanCondition signal];
    [_scanThread release_mm];
    _scanThread = nil;
    [_arraylockqueue dispatchThreadSync:^
    {
        for (XLGSendItem *i in _pool.items)
            [i suspendSendItem:YES];
        [_arQueue release_mm];
        _arQueue = nil;
    }];
}

- (void)enumeSendItem:(void (^)(NSUInteger nIndex, BOOL bIsend, XLGSendItem *item, BOOL *bStop))block
{
    [_arraylockqueue dispatchThreadSync:^
    {
        [_arQueue enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
        {
            block(idx, idx == _arQueue.count - 1, obj, stop);
        }];
    }];
}

- (void)openScanThread
{
    if([XLGContext context].m_bIsoffline == YES)
        return;
    
    if([XLGContext context].m_bIsofflinelogin == YES)
        return;
    
    if(_bSuspending == YES)
        return;
    
    if (nil == _scanThread)
    {
        _bRunloop = YES;
        _currentscaninterval = 1;
        _scanThread = [[NSThread alloc] initWithTarget:self selector:@selector(scanSendItemIndex) object:nil];
        [_scanThread start];
    }
    else
    {
        _currentscaninterval = 1;
        [_scanCondition signal];
    }
}

- (void)scanSendItemIndex
{
    @autoreleasepool
    {
        if (nil == _scanCondition)
            _scanCondition = [NSCondition new];
        
        while (YES == _bRunloop)
        {
            @autoreleasepool
            {
                __block NSUInteger nQueuecount = 0;
                [_arraylockqueue dispatchThreadSync: ^
                {
                    if (_pool.currentCount < _pool.maxCount && _arQueue.count > 0)
                    {
                        if (1 == _currentscaninterval)
                        {
                            XLGSendItem *si = [_arQueue objectAtIndex:MIN(_pool.currentCount, _pool.maxCount)];
                            XLGSendQueueIndex *mi = si.mi;
        #ifdef DEBUG
                            //				NSLog(@"ScanSendItemIndex1--id:%@,status:%i",mi.m_szExtendid,mi.m_nReadstatus);
        #endif
                            if (XLGSendItemStatusTypeUpprioritySend == mi.sendStatus || XLGSendItemStatusTypeWaiting == mi.sendStatus)
                            {
                                [_pool addSendOperation:si];
                            }
                            else if (XLGSendItemStatusTypeWaiting != mi.sendStatus && XLGSendItemStatusTypeUpprioritySend != mi.sendStatus &&
                                     XLGSendItemStatusTypeSending != mi.sendStatus)
                            {
        #ifdef DEBUG
                                //					NSLog(@"ScanSendItemIndex1--修改计时器");
        #endif
                                _currentscaninterval = _resendIntervalTime;
                                //	[m_scantimer fire];
                            }
                        }
                        else
                        {
        #ifdef DEBUG
                            //				NSLog(@"ScanSendItemIndex2");
        #endif
                            if (YES == [self resendAllFailedSendItem])
                            {
        #ifdef DEBUG
                                //					for(XLGSendItem* si in m_arQueue)
                                //					{
                                //						CMessageInstanceObj* mi=si.mi;
                                //						NSLog(@"resenditem--id:%@,num:%i,sendtype:%i,type:%i,title:%@",mi.m_szExtendid,mi.m_nStatus,mi.m_nReadstatus,mi.m_nMessagetype,mi.m_szTitle);
                                //					}
                                //					NSLog(@"ScanSendItemIndex2--修改计时器");
        #endif
                                [self exchangeAllSendItemStatus:XLGSendItemStatusTypeFailed toNewType:XLGSendItemStatusTypeWaiting];
                                
                                _currentscaninterval = 1;
                            }
                        }
                        
                    }
                    nQueuecount = _arQueue.count;
                }];

                if (nQueuecount <= 0)
                {
                    [_scanCondition lock];
                    [_scanCondition wait];
                    [_scanCondition unlock];
                }
                else
                {
                    [_scanCondition lock];
                    [_scanCondition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:_currentscaninterval]];
                    [_scanCondition unlock];
                }
            }
        }
        [_scanCondition release_mm];
        _scanCondition = nil;
    }
}

-(void)exchangeSendItemStatus:(XLGSendItem*)senditem
{
    [_uilockqueue dispatchThreadAsync:^
    {
        for (NSUInteger i = 0; i < _arSenditemanager.count; i++)
        {
            id<XLGSendQueueManagerDelegate> obj = [_arSenditemanager objectAtIndex:i];
            [obj exchangeManager:self sendItemStatus:senditem];
        }
    }];
}

-(void)exchangeAllSendItemStatus:(XLGSendItemStatusType)oldtype toNewType:(XLGSendItemStatusType)newtype
{
    [_uilockqueue dispatchThreadAsync:^
    {
        for (NSUInteger i = 0; i < _arSenditemanager.count; i++)
        {
            id<XLGSendQueueManagerDelegate> obj = [_arSenditemanager objectAtIndex:i];
            if([obj respondsToSelector:@selector(exchangeManager:allSendItemStatus:toNewType:)])
                [obj exchangeManager:self allSendItemStatus:oldtype toNewType:newtype];
        }
    }];
}

- (NSInteger)resendAllFailedSendItem
{
    BOOL b = NO;
    NSUInteger i = 0;
    for (NSUInteger j = 0; j < _arQueue.count; j++)
    {
        XLGSendItem *si = [_arQueue objectAtIndex:j];
        XLGSendQueueIndex *mi = si.mi;
        if (XLGSendItemStatusTypeNextTimeContinue == mi.sendStatus)
        {
            mi.sendStatus = XLGSendItemStatusTypeUpprioritySend;
            i++;
            b = YES;
        } else if (XLGSendItemStatusTypeFailed == mi.sendStatus || XLGSendItemStatusTypeRejest == mi.sendStatus)
        {
            mi.sendStatus = XLGSendItemStatusTypeWaiting;
            [_arQueue insertObject:si atIndex:i];
            [_arQueue removeObjectAtIndex:j + 1];
            i++;
            b = YES;
        }
        else if (XLGSendItemStatusTypeWaiting == mi.sendStatus)
        {
            i++;
        }
        else if (XLGSendItemStatusTypeUpprioritySend == mi.sendStatus)
        {
            i++;
        }
    }
    if (YES == b)
    {
        [_commonindex modifySendIndexStatus:^NSInteger(NSInteger(^modify)(NSUInteger index,NSString *extendID,NSUInteger sendStatus))
        {
            NSInteger nResult = FALSE;
            for (NSUInteger k = 0; k < _arQueue.count; k++)
            {
                XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:k]).mi;
                mi.serialNo = k;
                nResult = modify(mi.serialNo,mi.extendID,mi.sendStatus);
                if(nResult != YES)
                    break;
            }
            return nResult;
        }];
    }
    return b;
}

//- (NSInteger)modifySendItemIndex:(NSUInteger)index extendID:(NSString *)extendID
//{
//    return [_commonindex ModifyIndexOnTable:[NSString stringWithFormat:@"update %@ set status=%i where id='%@'", WAITINGSENDD, nStatus, extendid]];
//}

//- (NSInteger)modifySendIndexStatus:(NSUInteger)nStatus readStatus:(NSUInteger)nReadstatus condition:(NSString *)extendid
//{
////	return [_commonindex ModifyIndexOnTable:[NSString stringWithFormat:@"update %@ set status=%i where id='%@'",WAITINGSENDD,nStatus,extendid]];
//    return [_commonindex ModifyIndexOnTable:[NSString stringWithFormat:@"update %@ set status=%i,readstatus=%i where id='%@'", WAITINGSENDD, nStatus, nReadstatus, extendid]];
//}

- (NSInteger)deleteSendQueueItem:(NSString*)extendID
{
    __block BOOL bResult = NO;
    [_arraylockqueue dispatchThreadSync:^
    {
        NSUInteger nIndex = NSNotFound;
        XLGSendItem *senditem = nil;
        for (NSUInteger i = 0; i < _arQueue.count; i++)
        {
            senditem = [_arQueue objectAtIndex:i];
            if ([extendID isEqualToString:senditem.mi.extendID] == YES)
            {
                [[senditem retain_mm] autorelease_mm];
                nIndex = i;
                break;
            }
        }
        
        if(senditem.mi.sendStatus != XLGSendItemStatusTypeSending)
        {
            if (nIndex != NSNotFound && nIndex < _arQueue.count)
            {
                XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:nIndex]).mi;
                
                [_commonindex deleteSendIndexWithExtendID:@[mi.extendID]];
                
                [XMSFileHelper deleteFileDir:[NSString stringWithFormat:@"%@/%@/%@", [XLGContext context].m_szUserdefaulteppath, XLGSendQueueDataFolder, mi.extendID]];
                
                [_arQueue removeObjectAtIndex:nIndex];
                
                [_commonindex modifySendIndexSerialNo:^NSInteger(NSInteger (^modify)(NSUInteger index,NSString *extendID))
                {
                    NSInteger nResult = FALSE;
                    for (NSUInteger i = nIndex; i < _arQueue.count; i++)
                    {
                        XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:i]).mi;
                        mi.serialNo = i;
                        nResult = modify(i,mi.extendID);
                        if(nResult != YES)
                            break;
                    }
                    return nResult;
                }];
                
                bResult = YES;
                
                senditem.mi.sendStatus = XLGSendItemStatusTypeDelete;
                
                [self exchangeSendItemStatus:senditem];
                
                [senditem removeAllSendItemDelegate];
            }
        }
    }];
    return bResult;
}

- (void)delete:(NSString*)extendID delegate:(id<XLGSendQueueProgressViewDelegate>)delegate asyncCompletion:(void (^)(NSInteger))completion
{
    DispatchGlobalThreadAsync(^
    {
        @autoreleasepool
        {
            [delegate sendQueue:self beginProgressView:NSStringFromSelector(@selector(delete:delegate:asyncComplete:))];
            
            BOOL bResult = [self deleteSendQueueItem:extendID];

            [delegate sendQueueEndProgressView];
            
            completion(bResult);
        }
    });
}

- (void)stop:(NSString*)extendID delegate:(id<XLGSendQueueProgressViewDelegate>)delegate asyncCompletion:(void (^)(NSInteger))completion
{
    //暂停在前失败在后
    DispatchGlobalThreadAsync(^
    {
        @autoreleasepool
        {
            [delegate sendQueue:self beginProgressView:NSStringFromSelector(@selector(stop:delegate:asyncComplete:))];
            
            __block BOOL bResult = NO;
            [_arraylockqueue dispatchThreadSync:^
            {
                NSUInteger nIndex = NSNotFound;
                XLGSendItem *senditem = nil;
                for (NSUInteger i = 0; i < _arQueue.count; i++)
                {
                    senditem = [_arQueue objectAtIndex:i];
                    if ([extendID isEqualToString:senditem.mi.extendID] == YES)
                    {
                        [[senditem retain_mm] autorelease_mm];
                        nIndex = i;
                        break;
                    }
                }
                
                if (nIndex != NSNotFound && nIndex < _arQueue.count)
                {
                    XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:nIndex]).mi;
                    if (mi.sendStatus != XLGSendItemStatusTypeStop && mi.sendStatus != XLGSendItemStatusTypeSending)
                    {
                        mi.sendStatus = XLGSendItemStatusTypeStop;
                        NSUInteger i = 0;
                        for (; i < _arQueue.count; i++)
                        {
                            XLGSendQueueIndex *mm = ((XLGSendItem *) [_arQueue objectAtIndex:i]).mi;
                            if (mm.sendStatus == XLGSendItemStatusTypeFailed || mm.sendStatus == XLGSendItemStatusTypeRejest)
                                break;
                        }
                        if (nIndex < i)
                        {
                            [_arQueue insertObject:[_arQueue objectAtIndex:nIndex] atIndex:i];
                            [_arQueue removeObjectAtIndex:nIndex];
                            
                            [_commonindex modifySendIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger index,NSString *extendID,NSUInteger sendStatus))
                            {
                                NSInteger nResult = FALSE;
                                for (NSUInteger j = nIndex; j < i; j++)
                                {
                                    XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:j]).mi;
                                    mi.serialNo = j;
                                    nResult = modify(mi.serialNo,mi.extendID,mi.sendStatus);
                                    if(nResult != YES)
                                        break;
                                }
                                return nResult;
                            }];
                        }
                        else
                        {
                            [_arQueue insertObject:[_arQueue objectAtIndex:nIndex] atIndex:i];
                            [_arQueue removeObjectAtIndex:nIndex + 1];
                            
                            [_commonindex modifySendIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger index,NSString *extendID,NSUInteger sendStatus))
                            {
                                NSInteger nResult = FALSE;
                                for (NSUInteger j = i; j <= nIndex; j++)
                                {
                                    XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:j]).mi;
                                    mi.serialNo = j;
                                    nResult = modify(mi.serialNo,mi.extendID,mi.sendStatus);
                                    if(nResult != YES)
                                        break;
                                }
                                return nResult;
                            }];
                        }
                        bResult = YES;
                        
                        [self exchangeSendItemStatus:senditem];
                        
                        [senditem removeAllSendItemDelegate];
                        
#ifdef DEBUG
                        //			for(XLGSendItem* si in m_arQueue)
                        //			{
                        //				CMessageInstanceObj* mi=si.mi;
                        //				NSLog(@"stopitem--id:%@,num:%i,sendtype:%i,type:%i,title:%@",mi.m_szExtendid,mi.m_nStatus,mi.m_nReadstatus,mi.m_nMessagetype,mi.m_szTitle);
                        //			}
#endif
                    }
                }
            }];

            [delegate sendQueueEndProgressView];
            
            completion(bResult);
        }
    });
}

- (void)resend:(NSString*)extendID delegate:(id<XLGSendQueueProgressViewDelegate>)delegate asyncCompletion:(void (^)(NSInteger))completion
{
    DispatchGlobalThreadAsync(^
    {
        @autoreleasepool
        {
            [delegate sendQueue:self beginProgressView:NSStringFromSelector(@selector(resend:delegate:asyncComplete:))];
            __block BOOL bResult = NO;
            [_arraylockqueue dispatchThreadSync:^
            {
                NSUInteger nIndex = NSNotFound;
                XLGSendItem *senditem = nil;
                for (int i = 0; i < _arQueue.count; i++)
                {
                    senditem = [_arQueue objectAtIndex:i];
                    if ([extendID isEqualToString:senditem.mi.extendID] == YES)
                    {
                        [[senditem retain_mm] autorelease_mm];
                        nIndex = i;
                        break;
                    }
                }
                
                if (nIndex != NSNotFound && nIndex < _arQueue.count)
                {
                    XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:nIndex]).mi;
                    if (mi.sendStatus != XLGSendItemStatusTypeSending && mi.sendStatus != XLGSendItemStatusTypeUpprioritySend && mi.sendStatus != XLGSendItemStatusTypeWaiting)
                    {
                        mi.sendStatus = XLGSendItemStatusTypeWaiting;
                        NSInteger i = nIndex - 1;
                        for (; i >= 0; i--)
                        {
                            XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:i]).mi;
                            if (XLGSendItemStatusTypeSending == mi.sendStatus || XLGSendItemStatusTypeUpprioritySend == mi.sendStatus || XLGSendItemStatusTypeWaiting == mi.sendStatus)
                                break;
                        }
                        i++;
                        [_arQueue insertObject:[_arQueue objectAtIndex:nIndex] atIndex:i];
                        [_arQueue removeObjectAtIndex:nIndex + 1];
                        
                        [_commonindex modifySendIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger index,NSString *extendID,NSUInteger sendStatus))
                        {
                            NSInteger nResult = FALSE;
                            for (NSUInteger j = i; j <= nIndex; j++)
                            {
                                XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:j]).mi;
                                mi.serialNo = j;
                                nResult = modify(mi.serialNo,mi.extendID,mi.sendStatus);
                                if(nResult != YES)
                                    break;
                            }
                            return nResult;
                        }];
                        
                        bResult = YES;
                        
                        [self exchangeSendItemStatus:senditem];
                        
                        if (1 != _currentscaninterval)
                        {
                            _currentscaninterval = 1;
                            [_scanCondition signal];
                        }
                        
#ifdef DEBUG
                        //              for(XLGSendItem* si in m_arQueue)
                        //              {
                        //                  CMessageInstanceObj* mi=si.mi;
                        //                  NSLog(@"resenditem--id:%@,num:%i,sendtype:%i,type:%i,title:%@",mi.m_szExtendid,mi.m_nStatus,mi.m_nReadstatus,mi.m_nMessagetype,mi.m_szTitle);
                        //              }
#endif
                    }
                }
            }];

            [delegate sendQueueEndProgressView];
            
            completion(bResult);
        }
    });
}

- (void)upPriority:(NSString*)extendID delegate:(id<XLGSendQueueProgressViewDelegate>)delegate asyncCompletion:(void (^)(NSInteger))completion
{
    DispatchGlobalThreadAsync(^
    {
        @autoreleasepool
        {
            [delegate sendQueue:self beginProgressView:NSStringFromSelector(@selector(upPriority:delegate:asyncComplete:))];
            
            __block BOOL bResult = NO;
            [_arraylockqueue dispatchThreadSync:^
            {
                NSUInteger nIndex = NSNotFound;
                XLGSendItem *senditem = nil;
                for (int i = 0; i < _arQueue.count; i++)
                {
                    senditem = [_arQueue objectAtIndex:i];
                    if ([extendID isEqualToString:senditem.mi.extendID] == YES)
                    {
                        [[senditem retain_mm] autorelease_mm];
                        nIndex = i;
                        break;
                    }
                }
                
                if (nIndex != NSNotFound && nIndex < _arQueue.count)
                {
                    XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:nIndex]).mi;
                    if (XLGSendItemStatusTypeUpprioritySend == mi.sendStatus || XLGSendItemStatusTypeWaiting == mi.sendStatus || XLGSendItemStatusTypeStop == mi.sendStatus || XLGSendItemStatusTypeRejest == mi.sendStatus || XLGSendItemStatusTypeFailed == mi.sendStatus)
                    {
                        mi.sendStatus = XLGSendItemStatusTypeUpprioritySend;
                        NSInteger i = nIndex - 1;
                        for (; i >= 0; i--)
                        {
                            XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:i]).mi;
                            if (XLGSendItemStatusTypeSending == mi.sendStatus)
                                break;
                        }
                        i++;
                        [_arQueue insertObject:[_arQueue objectAtIndex:nIndex] atIndex:i];
                        [_arQueue removeObjectAtIndex:nIndex + 1];
                        
                        [_commonindex modifySendIndexStatus:^NSInteger(NSInteger (^modify)(NSUInteger index,NSString *extendID,NSUInteger sendStatus))
                        {
                            NSInteger nResult = FALSE;
                            for (NSUInteger j = i; j <= nIndex; j++)
                            {
                                XLGSendQueueIndex *mi = ((XLGSendItem *) [_arQueue objectAtIndex:j]).mi;
                                mi.serialNo = j;
                                nResult = modify(mi.serialNo,mi.extendID,mi.sendStatus);
                                if(nResult != YES)
                                    break;
                            }
                            return nResult;
                        }];
                        
                        
                        bResult = YES;
                        
                        [self exchangeSendItemStatus:senditem];
                        
                        if (1 != _currentscaninterval)
                        {
                            _currentscaninterval = 1;
                            [_scanCondition signal];
                        }
                        
#ifdef DEBUG
                        //              for(XLGSendItem* si in m_arQueue)
                        //              {
                        //                  CMessageInstanceObj* mi=si.mi;
                        //                  NSLog(@"uppriorityitem--id:%@,num:%i,sendtype:%i,type:%i,title:%@",mi.m_szExtendid,mi.m_nStatus,mi.m_nReadstatus,mi.m_nMessagetype,mi.m_szTitle);
                        //              }
#endif
                    }
                }
            }];
            
            [delegate sendQueueEndProgressView];
            
            completion(bResult);
        }
    });
}

- (void)terminalSendingItemWithSendItemID:(NSString*)sendItemID
{
    [self enumeSendItem:^(NSUInteger nIndex, BOOL bIsend, XLGSendItem *item, BOOL *bStop)
    {
        if([item.mi.extendID isEqualToString:sendItemID] && item.mi.sendStatus == XLGSendItemStatusTypeSending)
        {
            [item setForceTerminal:YES];
            *bStop = YES;
        }
    }];
}

-(BOOL)isNeedBackgroundMaintain
{
    if ([XLGContext context].m_bIsoffline == YES)
        return NO;
    
    if ([XLGContext context].m_bIsofflinelogin == YES)
        return NO;
    
    __block BOOL isNeed = NO;
    [self enumeSendItem:^(NSUInteger nIndex, BOOL bIsend, XLGSendItem *item, BOOL *bStop)
    {
        if(XLGSendItemStatusTypeSending == item.mi.sendStatus || XLGSendItemStatusTypeUpprioritySend == item.mi.sendStatus || XLGSendItemStatusTypeWaiting == item.mi.sendStatus)
        {
            isNeed = YES;
            *bStop = YES;
        }
    }];
    return isNeed;
}

static NSDictionary *s_sendQueueManager;

+ (void)initSendQueueManager
{
    if (s_sendQueueManager == nil)
    {
        s_sendQueueManager = [[NSDictionary dictionaryWithObject:[[XLGSendQueueManager new] autorelease_mm] forKey:XLGSendQueueManagerDefaultKey] retain_mm];
        [[s_sendQueueManager objectForKey:XLGSendQueueManagerDefaultKey] initSendQueueManager];
    }
}

+ (XLGSendQueueManager *)sendQueueManager
{
    return [s_sendQueueManager objectForKey:XLGSendQueueManagerDefaultKey];
}

+ (void)initMultiSendQueueManagerWithKey:(NSArray *)keys DBName:(NSArray *)DBNames
{
    if (s_sendQueueManager == nil)
    {
        NSMutableDictionary *dic = [[NSMutableDictionary new] autorelease_mm];
        for(NSInteger i = 0;i < keys.count;i++)
        {
            NSString *key = keys[i];
            [dic setObject:[[[XLGSendQueueManager alloc]initWithSendQueueDBFile:DBNames[i]] autorelease_mm] forKey:key];
        }
        s_sendQueueManager = [[NSDictionary dictionaryWithDictionary:dic] retain_mm];
        [s_sendQueueManager enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
        {
            [obj initSendQueueManager];
        }];
    }
}

+ (XLGSendQueueManager *)sendQueueManager:(NSString *)key
{
    return [s_sendQueueManager objectForKey:key];
}

+ (void)releaseSendQueueManager
{
    if(s_sendQueueManager != nil)
    {
        [s_sendQueueManager enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
        {
            [obj releaseSendQueueManager];
        }];
        [s_sendQueueManager release_mm];
        s_sendQueueManager = nil;
    }
}


+ (NSInteger)resumeSendQueueManager
{
    [s_sendQueueManager enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
    {
         [obj resumeSendQueueManager];
    }];
    return YES;
}

+ (void)suspendSendQueueManager
{
    [s_sendQueueManager enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
    {
        [obj suspendSendQueueManager];
    }];
}

@end
